﻿using System;
using System.Linq;
using OverSATbLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace OverSATbTest
{
    [TestClass]
    public class BasicTests
    {
        public static string TestValue;

        [TestMethod]
        public void ConvertAssignmentsToStrings()
        {
            OverSATbLib.Tuple asn1 = new OverSATbLib.Tuple(0, 1);
            OverSATbLib.Tuple asn2 = new OverSATbLib.Tuple(0, 1, -2, 3);
            OverSATbLib.Tuple asn3 = new OverSATbLib.Tuple(0, 1, -2, 3, -4, 5);

            Assert.AreEqual(asn1.ToString(),
@"0=1"
);

            Assert.AreEqual(asn2.ToString(),
@"0=1, -2=3"
);

            Assert.AreEqual(asn3.ToString(),
@"0=1, -2=3, -4=5"
);
        }

        [TestMethod]
        public void IntersectRanges()
        {
            Range baseRange, movingRange, intersection;

            baseRange = new Range(0, 10);
            movingRange = new Range(-20, -10);
            intersection = baseRange.Intersection(movingRange);
            Assert.IsTrue(intersection.Empty);

            movingRange = new Range(-5, 0);
            intersection = baseRange.Intersection(movingRange);
            Assert.IsTrue(intersection.Empty);

            movingRange = new Range(-5, 5 );
            intersection = baseRange.Intersection(movingRange);
            Assert.IsFalse(intersection.Empty);

            movingRange = new Range(0, 10);
            intersection = baseRange.Intersection(movingRange);
            Assert.IsFalse(intersection.Empty);

            movingRange = new Range(5, 15);
            intersection = baseRange.Intersection(movingRange);
            Assert.IsFalse(intersection.Empty);

            movingRange = new Range(10, 15);
            intersection = baseRange.Intersection(movingRange);
            Assert.IsTrue(intersection.Empty);

        }

        [TestMethod]
        public void MergeDeleteTuples()
        {
            OverSATbLib.Tuple pairA1 = new OverSATbLib.Tuple(3, 1, 2, 1, 1, 1);
            OverSATbLib.Tuple pairA2 = new OverSATbLib.Tuple(3, 1, 2, 1, 1, 1);

            var result = OverSATbLib.Tuple.MergeBitTuple(pairA1, pairA2);

            Assert.IsTrue(!result.Optimized, "Merge pair A should NOT have been optimized because it is an identity");
            Assert.IsTrue(!result.EntireSolutionIsFalse, "Merge pair A should not prove the entire solution is false");

            OverSATbLib.Tuple pairAB1 = new OverSATbLib.Tuple(3, 1, 2, 1, 1, 1);
            OverSATbLib.Tuple pairAB2 = new OverSATbLib.Tuple(3, 0, 2, 0, 1, 0);

            var resultAB = OverSATbLib.Tuple.MergeBitTuple(pairAB1, pairAB2);
            Assert.IsTrue(resultAB.Optimized, "Merge pair AB should have been optimized");
            Assert.IsTrue(resultAB.TuplesToAdd.Count == 0 && resultAB.TuplesToRemove[0] == pairAB1 && resultAB.TuplesToRemove[1] == pairAB2, "Merge pair AB should be a pure cancel");
            Assert.IsTrue(resultAB.EntireSolutionIsFalse, "Merge pair AB should prove the entire solution is false");

            OverSATbLib.Tuple pairB1 = new OverSATbLib.Tuple(3, 1, 2, 1, 1, 1);
            OverSATbLib.Tuple pairB2 = new OverSATbLib.Tuple(3, 1, 1, 1);

            var resultB = OverSATbLib.Tuple.MergeBitTuple(pairB1, pairB2);

            Assert.IsTrue(!resultB.Optimized, "Merge pair B should not have been optimized");
            Assert.IsTrue(!resultB.EntireSolutionIsFalse, "Merge pair B should not prove the entire solution is false");

            OverSATbLib.Tuple pairC1 = new OverSATbLib.Tuple(3, 1, 2, 1, 1, 1);
            OverSATbLib.Tuple pairC2 = new OverSATbLib.Tuple(3, 1, 2, 1);

            var resultC = OverSATbLib.Tuple.MergeBitTuple(pairC1, pairC2);

            Assert.IsTrue(resultC.Optimized, "Merge pair C should have been optimized");
            Assert.IsTrue(resultC.TuplesToRemove[0] == pairC1 && resultC.TuplesToAdd[0].AssignItems.Sum( x => x.NameId ) == 5, "Merge pair C should have been optimized as a tail removing substitution");
            Assert.IsTrue(!resultC.EntireSolutionIsFalse, "Merge pair C should not prove the entire solution is false");

            OverSATbLib.Tuple pairD1 = new OverSATbLib.Tuple(4, 1, 3, 0, 1, 0);
            OverSATbLib.Tuple pairD2 = new OverSATbLib.Tuple(3, 1, 1, 1);

            var resultD = OverSATbLib.Tuple.MergeBitTuple(pairD1, pairD2);

            Assert.IsTrue(resultD.Optimized, "Merge pair D should have been optimized");
            Assert.IsTrue(resultD.TuplesToRemove[0] == pairD1 && resultD.TuplesToAdd[0].AssignItems.Sum( x => x.NameId ) == 4, "Merge pair D should have been optimized");
            Assert.IsTrue(!resultD.EntireSolutionIsFalse, "Merge pair D should not prove the entire solution is false");

            var resultDB = OverSATbLib.Tuple.MergeBitTuple(pairD2, pairD1);

            Assert.IsTrue(resultDB.Optimized, "Merge pair DB should have been optimized the same as pair D");
            Assert.IsTrue(resultDB.TuplesToRemove[0] == pairD1 && resultD.TuplesToAdd[0].AssignItems.Sum(x => x.NameId) == 4, "Merge pair DB should have been optimized the same as pair D");
            Assert.IsTrue(!resultDB.EntireSolutionIsFalse, "Merge pair DB should not prove the entire solution is false");

            OverSATbLib.Tuple pairE1 = new OverSATbLib.Tuple(4, 1, 3, 0, 1, 0);
            OverSATbLib.Tuple pairE2 = new OverSATbLib.Tuple(4, 1, 3, 1);

            var resultE = OverSATbLib.Tuple.MergeBitTuple(pairE1, pairE2);
            Assert.IsTrue(resultE.Optimized, "Merge pair E should have been optimized");
            Assert.IsTrue(resultE.TuplesToRemove[0] == pairE1 && resultE.TuplesToAdd[0].AssignItems.Sum(x => x.NameId) == 5, "Merge pair E have had id 3 removed and kept id 1");
        }

        [TestMethod]
        public void IntersectTuples()
        {
            OverSATbLib.Tuple pA1 = new OverSATbLib.Tuple(1, 1, 2, 1, 3, 1);
            OverSATbLib.Tuple pA2 = new OverSATbLib.Tuple(1, 1, 2, 1, 3, 1);
            OverSATbLib.Tuple pAI = pA1.Intersection(pA2);
            string sA = pAI.ToBitString();
            Assert.IsTrue(sA == "1 2 3", "pA tuple must be 1 2 3");

            OverSATbLib.Tuple pB1 = new OverSATbLib.Tuple(1, 1, 2, 0, 3, 1);
            OverSATbLib.Tuple pB2 = new OverSATbLib.Tuple(1, 1, 2, 1, 3, 1);
            OverSATbLib.Tuple pBI = pB1.Intersection(pB2);
            Assert.IsNull(pBI, "pB Tuples should not intersect.");

            OverSATbLib.Tuple pC1 = new OverSATbLib.Tuple(1, 1, 2, 1, 3, 1, 4, 1, 5, 0, 6, 1, 7, 0);
            OverSATbLib.Tuple pC2 = new OverSATbLib.Tuple(1, 1, 2, 1, 3, 1);
            OverSATbLib.Tuple pCI = pC1.Intersection(pC2);
            string sC = pCI.ToBitString();
            Assert.IsTrue(sC == "1 2 3 4 -5 6 -7", "pC tuple must be 1 2 3 4 -5 6 -7");

        }

    }

}
